package com.share.common.utils.plugin.applicationEvent;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;


/**
 * 
 * @author lenovo
 *
 * @param <E> 事件具体实现类
 */
public abstract class EventHookSupport<E extends ApplicationEvent> implements EventHook<E>{

	@Autowired
    protected EventHooksManager eventPluginManager;
    @Autowired
	private ApplicationContext applicationContext;
    
    @SuppressWarnings("rawtypes")
	protected Map<String, EventListenerPlugin> plugins;

    /**
     * 事件插件初始化，编写Event钩子时，应该编写此方法，方法应有以下内容
     * <p>
     * 如：this.plugins = getPlugins(FeedsEventListener.class);
     * <p>
     * 其中FeedsEventListener是继承EventListener的接口，拥有区分一类钩子下的所有插件
     */
    
	@PostConstruct
    public abstract void init();

    /**
     * 事件插件注销
     */
    @PreDestroy
    public void destroy() {
    	eventPluginManager.removeHook(this);
    }

    /**
     * 获取泛型中的类型，用于区分该钩子是处理哪个Event，顾编写钩子的时候理应用泛型
     * <p>
     * 如：public class FeedsEventHook extends EventHookSupport<FeedsEvent>
     *
     * @return
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Class getEventClass() {
        Class clazz = getClass();
        while (clazz != Object.class) {
            Type t = clazz.getGenericSuperclass();
            if (t instanceof ParameterizedType) {
                Type[] args = ((ParameterizedType) t).getActualTypeArguments();
                if (args[0] instanceof Class) {
                    clazz = (Class<E>) args[0];
                    break;
                }
            }
            clazz = clazz.getSuperclass();
        }
        return clazz;
    }

    /**
     * 获取此钩子下的所有插件,调用此方法时会获取所有Event钩子的插件
     *
     * @return
     */
    @SuppressWarnings("rawtypes")
	protected Map<String, EventListenerPlugin> getPlugins() {
        return getPlugins(EventListenerPlugin.class);
    }

    /**
     * 获取插件
     * @param clazz
     * @return
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	public Map<String, EventListenerPlugin> getPlugins(Class clazz) {
        return applicationContext.getBeansOfType(clazz);
    }
    
    /**
     * 调用插件处理事件
     * @param event
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected void onEvent(ApplicationEvent event){
		Iterator<Map.Entry<String, EventListenerPlugin>> it = this.plugins.entrySet().iterator();
        while (it.hasNext()) {
            it.next().getValue().onEvent(event);
        }
    }
}
